namespace miscUtils {
	export function getGameStr(key: string, id: number): string {
		if (key === 'npc') {
			const xls = getNpcInfo(id);
			const prefix = getColorPrefix(xls.Display.color) || '#G';
			return `${prefix}${xls ? xls.Display.name : String(id)}#n#h(${xls.Display.icon})`;
		}
		if (key === 'item') {
			const xls = getAnyItemInfo(id);
			if (!xls) {
				return String(id);
			}
			const info = getColorInfoByRank(xls.Rank);
			return `#z(${miscUtils.color2Hex(info.Color)})${xls ? xls.Name : String(id)}#n#t(${
				xls.Icon
			})`;
		}
		return String(id);
	}

	export function formatGameString(str: string): string {
		const keywords = ['npc', 'item'];
		for (const key of keywords) {
			const re = new RegExp(`\\$${key}\\((\\d+)\\)`, 'g');
			const rt = str.match(re);
			// console.log(str, key, rt);
			if (rt) {
				for (const s of rt) {
					const sid = s.substring(key.length + 2, s.length - 1);
					const id = Number(sid);
					// console.log('match', key, id, rt);
					// console.log(str[rt.index])
					str = str.replace(s, getGameStr(key, id));
				}
			}
		}
		return str;
	}

	const hyphenated = [
		'欧阳',
		'太史',
		'端木',
		'上官',
		'司马',
		'东方',
		'独孤',
		'南宫',
		'万俟',
		'闻人',
		'夏侯',
		'诸葛',
		'尉迟',
		'公羊',
		'赫连',
		'澹台',
		'皇甫',
		'宗政',
		'濮阳',
		'公冶',
		'太叔',
		'申屠',
		'公孙',
		'慕容',
		'仲孙',
		'钟离',
		'长孙',
		'宇文',
		'城池',
		'司徒',
		'鲜于',
		'司空',
		'汝嫣',
		'闾丘',
		'子车',
		'亓官',
		'司寇',
		'巫马',
		'公西',
		'颛孙',
		'壤驷',
		'公良',
		'漆雕',
		'乐正',
		'宰父',
		'谷梁',
		'拓跋',
		'夹谷',
		'轩辕',
		'令狐',
		'段干',
		'百里',
		'呼延',
		'东郭',
		'南门',
		'羊舌',
		'微生',
		'公户',
		'公玉',
		'公仪',
		'梁丘',
		'公仲',
		'公上',
		'公门',
		'公山',
		'公坚',
		'左丘',
		'公伯',
		'西门',
		'公祖',
		'第五',
		'公乘',
		'贯丘',
		'公皙',
		'南荣',
		'东里',
		'东宫',
		'仲长',
		'子书',
		'子桑',
		'即墨',
		'达奚',
		'褚师',
	];

	export function getXingming(fullname: string): [string, string] {
		const vLength = fullname.length;
		let lastname = '';
		let firstname = '';
		if (vLength > 2) {
			const preTwoWords = fullname.substr(0, 2);
			// 取命名的前两个字,看是否在复姓库中
			if (hyphenated.indexOf(preTwoWords) !== -1) {
				firstname = preTwoWords;
				lastname = fullname.substr(2);
			} else {
				firstname = fullname.substr(0, 1);
				lastname = fullname.substr(1);
			}
		} else if (vLength === 2) {
			// 全名只有两个字时,以前一个为姓,后一下为名
			firstname = fullname.substr(0, 1);
			lastname = fullname.substr(1);
		} else {
			firstname = fullname;
		}
		return [firstname, lastname];
	}

	// ${sx}=>少侠!
	export function replaceCall(p: Player, s: string): string {
		if (!p || !p.id) {
			return s;
		}
		const name = p.getName();
		const [xing, ming] = getXingming(name);
		const calls = {
			sx: ['少侠', '女侠'],
			gz: ['公子', '姑娘'],
			gg: ['哥哥', '姐姐'],
			dd: ['弟弟', '妹妹'],
			xg: ['小哥', '小妹'],
			xz: ['小子', '丫头'],
			sz: ['孙儿', '孙女'],
			sj: ['师兄', '师姐'],
			sd: ['师弟', '师妹'],
			xd: ['贤弟', '贤妹'],
			ta: ['他', '她'],
			xxd: ['小弟', '小妹'],
		};
		const sex = p.getSex();
		const vars = {
			name,
			xing,
			ming,
		};

		for (const [key, v] of Object.entries(calls)) {
			vars[key] = v[sex];
		}
		const school = p.getSchool();
		const shili = p.getShili();
		vars['school'] = school ? getOrgInfo(school).Name : '江湖';
		vars['shili'] = shili ? getOrgInfo(shili).Name : '势力';
		// const matches = s.matchAll(/${\w+}/);
		return Utils.formatString(s, vars);
	}

	export function formatCallMsg(text: string, ni1: string, ni2: string, wo: string): string {
		if (wo) {
			text = text.replaceRawAll('${wo}', wo);
		}
		const ni = getPlayerClient().isMale() ? ni1 : ni2;
		if (ni) {
			text = text.replaceRawAll('${ni}', ni);
		}
		// if (ta) {
		// 	text = text.replaceRawAll('${ta}', ta); //${ta(1000)}
		// }
		return text;
	}

	function getCallCondName(ta: CallType): string {
		if (typeof ta === 'string') {
			return ta;
		}
		const p = getPlayerClient();
		for (const t of ta) {
			const [cond, name] = t;
			if (cond === 0) {
				return name;
			}
			if (testCondition(p, cond)) {
				return name;
			}
		}
		return '';
	}

	export function formatCallTa(s: string): string {
		const find = /\$\{ta\}\((\d+)\)/;

		while (true) {
			const f = s.match(find);
			if (f && f[1]) {
				const id = Number(f[1]);
				const xls = getCallInfo(id);
				if (xls) {
					s =
						s.substr(0, f.index) +
						(getCallCondName(xls.Ta) || xls.Name) +
						s.substr(f.index + 7 + f[1].length);
				} else {
					break;
				}
			} else {
				break;
			}
		}
		return s;
	}

	export function formatNpcMsg(id: number, text: string): string {
		text = formatCallTa(text);

		const xls2 = getNpcInfo(id);
		if (!xls2) {
			return text;
		}
		const xls = getCallInfo(xls2.Call);
		if (!xls) {
			return text;
		}
		text = formatCallMsg(
			text,
			getCallCondName(xls.Ni),
			getCallCondName(xls.Ni2),
			getCallCondName(xls.Wo),
		);
		// 他
		// let find = text.match('${ta}()')

		return text;
	}

	export function formatNpcMsgAll(id: number, msg: string): string {
		msg = formatNpcMsg(id, msg);
		msg = miscUtils.replaceCall(getPlayerClient(), String(msg));
		msg = miscUtils.formatGameString(msg);
		return msg;
	}
}
